package org.example.springmybatisdemo.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.example.springmybatisdemo.entity.Result;
import org.example.springmybatisdemo.utils.JwtUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {

    /**
     * 返回错误响应（统一JSON格式）
     */
    private void returnErrorResponse(HttpServletResponse response, Result result) throws IOException {
        response.setStatus(result.getCode());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");

        // 使用Jackson序列化Result对象
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(result);

        try (PrintWriter writer = response.getWriter()) {
            writer.write(json);
            writer.flush();
        }
    }

//    ctrl + o 重新生成 重写
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        log.info("Interceptor postHandle");

        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //        在拦截器中处理 OPTIONS 请求（推荐）
        // 0. 放行OPTIONS请求（预检请求）
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK); // 返回200
            return true;
        }

        log.info("Interceptor preHandle");
        //        1. 获取请求url
        String uri = request.getRequestURI();
        log.info("Interceptor preHandle url = {}", uri);
//        2.判断请求url是否包含login 如果包含说明是登录操作 放行
        System.out.println("地址" + uri);
        System.out.println(("测试" + uri.contains("swagger-ui")));
        // 放行登录和Swagger/OpenAPI相关路径
        if (uri.contains("login") ||
                uri.startsWith("/swagger") ||
                uri.startsWith("/v3/api-docs") ||
                uri.startsWith("/webjars") ||
                uri.equals("/doc.html") ||
                uri.equals("/favicon.ico") ||
                uri.startsWith("/swagger-resources") ||
                uri.startsWith("/api/depts/geterror")
                ||
                uri.contains("/uploadlocal")

        ) {
            HandlerInterceptor.super.preHandle(request, response, handler);
            return true;
        }

//        3. 获取请求头中的令牌
        String token = request.getHeader("token");

//        4. 判断令牌是否存在，如果不存在返回401
        if (token == null) {
            log.warn("令牌不存在");
//            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            returnErrorResponse(response, Result.fail("未授权，请提供有效令牌", 401));
//            不放行
            return false;
        }

//        5. 解析token， 如果解析失败返回401
        try {
            Claims claims = JwtUtils.parseJwt(token);
            log.info("令牌解析成功", claims);
        } catch (Exception e) {
            log.warn("令牌解析失败");
            returnErrorResponse(response, Result.fail("令牌无效或已过期", 401));
            e.printStackTrace();
//            response.setStatus(HttpStatus.UNAUTHORIZED.value());
//            不放行
            return false;
        }

//        6.放行
        return true;
//        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("Interceptor afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
